{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Simple Fully Connected Autoencoder\n",
    "This example demonstrate how to create and use a simple fully connected autoencoder for anomaly detection on data streams. The example uses the `CreditCard` dataset from the river library and shows how the module integrates into the river ecosystem."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-28T08:11:20.387808Z",
     "iopub.status.busy": "2025-09-28T08:11:20.387488Z",
     "iopub.status.idle": "2025-09-28T08:11:30.422822Z",
     "shell.execute_reply": "2025-09-28T08:11:30.422286Z"
    }
   },
   "outputs": [],
   "source": [
    "from river import compose, preprocessing, metrics, datasets\n",
    "from deep_river.anomaly import Autoencoder\n",
    "from torch import nn, manual_seed\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Analyse\n",
    "This code initializes a reproducible environment and loads a subset of the CreditCard dataset, selecting 5000 transactions for analysis. It then converts the dataset into a Pandas DataFrame and generates a summary report using TableReport(), which provides an overview of the dataset's structure, feature distributions, and potential missing values. This step helps to understand the data before applying preprocessing or modeling techniques."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-28T08:11:30.425709Z",
     "iopub.status.busy": "2025-09-28T08:11:30.425380Z",
     "iopub.status.idle": "2025-09-28T08:11:30.430940Z",
     "shell.execute_reply": "2025-09-28T08:11:30.430312Z"
    }
   },
   "outputs": [],
   "source": [
    "_ = manual_seed(42)\n",
    "dataset = datasets.CreditCard().take(5000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Model Creation\n",
    "This block sets up an anomaly detection pipeline using an autoencoder-based neural network. It begins by loading a subset of the CreditCard dataset and defining a rolling ROC AUC metric to evaluate model performance dynamically over a window of 5000 samples. The `MyAutoEncoder` class constructs a simple autoencoder with a bottleneck layer of configurable dimensionality (`latent_dim=3`), using LeakyReLU activation for encoding and a sigmoid function for reconstruction. A pipeline is then created, consisting of a `MinMaxScaler` for feature normalization and the autoencoder wrapped within `AutoencoderInitialized`, optimizing it with a learning rate of 0.005. This setup enables online learning, where the model updates continuously as new data arrives."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-28T08:11:30.433454Z",
     "iopub.status.busy": "2025-09-28T08:11:30.433256Z",
     "iopub.status.idle": "2025-09-28T08:11:31.353419Z",
     "shell.execute_reply": "2025-09-28T08:11:31.352604Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div><div class=\"river-component river-pipeline\"><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">MinMaxScaler</pre></summary><code class=\"river-estimator-params\">MinMaxScaler ()\n",
       "</code></details><details class=\"river-component river-estimator\"><summary class=\"river-summary\"><pre class=\"river-estimator-name\">Autoencoder</pre></summary><code class=\"river-estimator-params\">Autoencoder (\n",
       "  module=MyAutoEncoder(\n",
       "  (linear1): Linear(in_features=30, out_features=3, bias=True)\n",
       "  (nonlin): LeakyReLU(negative_slope=0.01)\n",
       "  (linear2): Linear(in_features=3, out_features=30, bias=True)\n",
       "  (sigmoid): Sigmoid()\n",
       ")\n",
       "  loss_fn=\"mse\"\n",
       "  optimizer_fn=\"sgd\"\n",
       "  lr=0.005\n",
       "  is_feature_incremental=False\n",
       "  device=\"cpu\"\n",
       "  seed=42\n",
       ")\n",
       "</code></details></div><style scoped>\n",
       ".river-estimator {\n",
       "    padding: 1em;\n",
       "    border-style: solid;\n",
       "    background: white;\n",
       "    max-width: max-content;\n",
       "}\n",
       "\n",
       ".river-pipeline {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "    align-items: center;\n",
       "    background: linear-gradient(#000, #000) no-repeat center / 1.5px 100%;\n",
       "}\n",
       "\n",
       ".river-union {\n",
       "    display: flex;\n",
       "    flex-direction: row;\n",
       "    align-items: center;\n",
       "    justify-content: center;\n",
       "    padding: 1em;\n",
       "    border-style: solid;\n",
       "    background: white;\n",
       "}\n",
       "\n",
       ".river-wrapper {\n",
       "    display: flex;\n",
       "    flex-direction: column;\n",
       "    align-items: center;\n",
       "    justify-content: center;\n",
       "    padding: 1em;\n",
       "    border-style: solid;\n",
       "    background: white;\n",
       "}\n",
       "\n",
       ".river-wrapper > .river-estimator {\n",
       "    margin-top: 1em;\n",
       "}\n",
       "\n",
       "/* Vertical spacing between steps */\n",
       "\n",
       ".river-component + .river-component {\n",
       "    margin-top: 2em;\n",
       "}\n",
       "\n",
       ".river-union > .river-estimator {\n",
       "    margin-top: 0;\n",
       "}\n",
       "\n",
       ".river-union > .river-component {\n",
       "    margin-top: 0;\n",
       "}\n",
       "\n",
       ".river-union > .pipeline {\n",
       "    margin-top: 0;\n",
       "}\n",
       "\n",
       "/* Spacing within a union of estimators */\n",
       "\n",
       ".river-union > .river-component + .river-component {\n",
       "    margin-left: 1em;\n",
       "}\n",
       "\n",
       "/* Typography */\n",
       "\n",
       ".river-estimator-params {\n",
       "    display: block;\n",
       "    white-space: pre-wrap;\n",
       "    font-size: 110%;\n",
       "    margin-top: 1em;\n",
       "}\n",
       "\n",
       ".river-estimator > .river-estimator-params,\n",
       ".river-wrapper > .river-details > river-estimator-params {\n",
       "    background-color: white !important;\n",
       "}\n",
       "\n",
       ".river-wrapper > .river-details {\n",
       "    margin-bottom: 1em;\n",
       "}\n",
       "\n",
       ".river-estimator-name {\n",
       "    display: inline;\n",
       "    margin: 0;\n",
       "    font-size: 110%;\n",
       "}\n",
       "\n",
       "/* Toggle */\n",
       "\n",
       ".river-summary {\n",
       "    display: flex;\n",
       "    align-items:center;\n",
       "    cursor: pointer;\n",
       "}\n",
       "\n",
       ".river-summary > div {\n",
       "    width: 100%;\n",
       "}\n",
       "</style></div>"
      ],
      "text/plain": [
       "Pipeline (\n",
       "  MinMaxScaler (),\n",
       "  Autoencoder (\n",
       "    module=MyAutoEncoder(\n",
       "    (linear1): Linear(in_features=30, out_features=3, bias=True)\n",
       "    (nonlin): LeakyReLU(negative_slope=0.01)\n",
       "    (linear2): Linear(in_features=3, out_features=30, bias=True)\n",
       "    (sigmoid): Sigmoid()\n",
       "  )\n",
       "    loss_fn=\"mse\"\n",
       "    optimizer_fn=\"sgd\"\n",
       "    lr=0.005\n",
       "    is_feature_incremental=False\n",
       "    device=\"cpu\"\n",
       "    seed=42\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dataset = datasets.CreditCard().take(5000)\n",
    "metric = metrics.RollingROCAUC(window_size=5000)\n",
    "class MyAutoEncoder(nn.Module):\n",
    "    def __init__(self, n_features, latent_dim=3):\n",
    "        super(MyAutoEncoder, self).__init__()\n",
    "        self.linear1 = nn.Linear(n_features, latent_dim)\n",
    "        self.nonlin = nn.LeakyReLU()\n",
    "        self.linear2 = nn.Linear(latent_dim, n_features)\n",
    "        self.sigmoid = nn.Sigmoid()\n",
    "\n",
    "    def forward(self, X, **kwargs):\n",
    "        X = self.linear1(X)\n",
    "        X = self.nonlin(X)\n",
    "        X = self.linear2(X)\n",
    "        return self.sigmoid(X)\n",
    "\n",
    "\n",
    "model_pipeline = compose.Pipeline(\n",
    "    preprocessing.MinMaxScaler(), \n",
    "    Autoencoder(module=MyAutoEncoder(30), lr=0.005)\n",
    ")\n",
    "model_pipeline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Run the Datastream\n",
    "This block performs hyperparameter optimization by evaluating the impact of different latent dimensions on the model's performance. It iterates over a predefined set of `latent_dim` values, initializing a fresh dataset and rolling ROC AUC metric for each experiment. A pipeline is created for each latent dimension, consisting of a `MinMaxScaler` for normalization and an autoencoder trained using online learning. The model is then trained and evaluated sequentially on the dataset, updating the metric with its predictions. After processing all data points, the final ROC AUC score is recorded for the current latent dimension. Once all experiments are completed, the results are stored in a DataFrame and visualized using a line plot, where the x-axis represents the latent dimension values and the y-axis represents the corresponding ROC AUC scores. This visualization helps identify the optimal latent dimension for anomaly detection."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-28T08:11:31.388222Z",
     "iopub.status.busy": "2025-09-28T08:11:31.387844Z",
     "iopub.status.idle": "2025-09-28T08:11:35.437707Z",
     "shell.execute_reply": "2025-09-28T08:11:35.437082Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ROCAUC: 0.8901\n"
     ]
    }
   ],
   "source": [
    "for x, y in dataset:\n",
    "    score = model_pipeline.score_one(x)\n",
    "    metric.update(y_true=y, y_pred=score)\n",
    "    model_pipeline.learn_one(x=x)\n",
    "print(f\"ROCAUC: {metric.get():.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Hyperparameter Optimization\n",
    "This block processes the dataset sequentially, evaluating and updating the model in an online learning manner. For each data point, the model generates an anomaly score using `score_one(x)`, which is then used to update the rolling ROC AUC metric by comparing it to the true label `y`. After scoring, the model is trained incrementally using `learn_one(x)`, allowing it to adapt continuously as new data arrives. Once all data points have been processed, the final ROC AUC score is printed, providing a performance measure of the model's ability to distinguish between fraudulent and non-fraudulent transactions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-28T08:11:35.440376Z",
     "iopub.status.busy": "2025-09-28T08:11:35.440173Z",
     "iopub.status.idle": "2025-09-28T08:11:35.443800Z",
     "shell.execute_reply": "2025-09-28T08:11:35.442832Z"
    }
   },
   "outputs": [],
   "source": [
    "latent_dims = [2, 5, 10, 20, 30, 40]  # You can adjust this range\n",
    "results = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "execution": {
     "iopub.execute_input": "2025-09-28T08:11:35.447307Z",
     "iopub.status.busy": "2025-09-28T08:11:35.446868Z",
     "iopub.status.idle": "2025-09-28T08:11:57.864675Z",
     "shell.execute_reply": "2025-09-28T08:11:57.864095Z"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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9vvvv6N69eo6IZuIKC8MvERUqiUkJODMmTNay8qXL4+qVasiIyMDixcvRpcuXfD7779j+fLlWtsFBATg2bNniI6ORmhoKBwcHFC9enX069cPAwcOxLx581C3bl08fPgQ0dHRCAkJQadOnWTVFRAQgL179+LKlSsoX748XFxcdHox1dLS0nD//n1kZWUhLi4Oe/bswezZs9G5c2cMHDiwUO2Sl5kzZ2L06NFwcXFB+/btkZaWhj///BNPnz7FuHHjZO1jzJgx6NChA6pXr46nT5/i4MGDqFmzpt5tx48fj1deeQUfffQRevXqhWPHjmHJkiVaV4YgIioIL0tGRKXaoUOHULduXa3bzJkzERoaiqioKMyZMwe1a9fGN998g9mzZ2s9t1GjRhg5ciR69eoFd3d3fP755wCANWvWYODAgRg/fjwCAwPRrVs3nDx5EhUrVpRd1/DhwxEYGIj69evD3d1dp5czpz179sDb2xsBAQFo3749Dh48iEWLFuHbb781ei/osGHDsHLlSqxZswbBwcFo3rw5vv766wKHTuSUlZWFt99+GzVr1kT79u1RvXr1PANsvXr1sHXrVmzevBm1a9fGtGnTMGvWLAwePNhI74iISgOVMPagMSIiIiIiE8IeXiIiIiIyawy8RERERGTWGHiJiIiIyKwx8BIRERGRWWPgJSIiIiKzxsBLRERERGaNgZeIiIiIzBoDLxERERGZNQZeIiIiIjJrDLxEREREZNYYeImIiIjIrP0fF6prDYSMX90AAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 800x500 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for latent_dim in latent_dims:\n",
    "    # Initialize a fresh metric\n",
    "    dataset = datasets.CreditCard().take(5000)\n",
    "    metric = metrics.RollingROCAUC(window_size=5000)\n",
    "\n",
    "    # Initialize pipeline with current latent_dim\n",
    "    model_pipeline = compose.Pipeline(\n",
    "        preprocessing.MinMaxScaler(),\n",
    "        Autoencoder(module=MyAutoEncoder(30, latent_dim), lr=0.005)\n",
    "    )\n",
    "\n",
    "    # Train and evaluate model\n",
    "    for x, y in dataset:\n",
    "        score = model_pipeline.score_one(x)\n",
    "        metric.update(y_true=y, y_pred=score)\n",
    "        model_pipeline.learn_one(x=x)\n",
    "\n",
    "    # Store the result\n",
    "    results.append((latent_dim, metric.get()))\n",
    "\n",
    "# Convert results to DataFrame for visualization\n",
    "df_results = pd.DataFrame(results, columns=[\"latent_dim\", \"ROCAUC\"])\n",
    "\n",
    "# Plot results\n",
    "plt.figure(figsize=(8, 5))\n",
    "plt.plot(df_results[\"latent_dim\"], df_results[\"ROCAUC\"], marker=\"o\", linestyle=\"-\", color=\"b\")\n",
    "plt.xlabel(\"Latent Dimension\")\n",
    "plt.ylabel(\"ROCAUC Score\")\n",
    "plt.title(\"Hyperparameter Optimization: Latent Dimension vs. ROCAUC\")\n",
    "plt.grid(True)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "deep-river",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
